package com.xlh.virtualization.controller;

import com.github.pagehelper.PageInfo;
import com.xlh.common.Result;
import com.xlh.common.ResultEnum;
import com.xlh.enums.LocalResourcesEnum;
import com.xlh.exception.common.GlobalException;
import com.xlh.security.UserInfoHolder;
import com.xlh.vo.PageVO;
import com.xlh.virtualization.domain.Image;
import com.xlh.virtualization.domain.ImageAttr;
import com.xlh.virtualization.po.ImageImportPO;
import com.xlh.virtualization.po.ImageQuotaUpdatePO;
import com.xlh.virtualization.service.ConfigService;
import com.xlh.virtualization.service.ImageAllocationService;
import com.xlh.virtualization.service.ImageService;
import com.xlh.vo.IconVO;
import com.xlh.virtualization.vo.ImageDetailVO;
import com.xlh.virtualization.vo.ImageVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author cheer
 */
@Api("镜像管理")
@RestController
@RequestMapping("/image")
public class ImageController {

    @Autowired
    private UserInfoHolder userInfoHolder;

    @Autowired
    private ImageService imageService;

    @Autowired
    private ImageAllocationService imageAllocationService;

    @Autowired
    private ConfigService configService;

    @ApiOperation("查询镜像图标列表")
    @GetMapping("/icon")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result<List<IconVO>> queryImageIcons() {
        List<IconVO> iconVOS = imageService.listImageIcons();
        return Result.success(iconVOS);
    }

    @ApiOperation("分页查询公共镜像列表")
    @GetMapping("/page")
    @PreAuthorize("@permissionValidator.isAdmin()")
    public Result<PageVO<ImageDetailVO>> querySharedImagesByPage(@RequestParam(required = false, defaultValue = "1") Integer pageNum,
                                                                 @RequestParam(required = false, defaultValue = "10") Integer pageSize,
                                                                 @RequestParam(required = false) Long imageSource) {
        if (imageSource == 0) {
            imageSource = null;
        }
        PageInfo<ImageAttr> pageInfo = imageService.listSharedImagesByPage(pageNum, pageSize, imageSource);

        List<ImageDetailVO> imageDetailVOS = new ArrayList<>();
        for (ImageAttr imageAttr : pageInfo.getList()) {
            ImageDetailVO imageDetailVO = ImageDetailVO.builder()
                    .imageId(imageAttr.getImageId())
                    .imageName(imageAttr.getImageName())
                    .imageNameInDocker(userInfoHolder.isSuperAdmin() ? imageAttr.getImageNameInDocker() : null)
                    .iconUrl(LocalResourcesEnum.SYSTEM_FILE.getMappingUrl(imageAttr.getIconUrl()))
                    .description(imageAttr.getDescription())
                    .imageSource(imageAttr.getImageSource())
                    .username(imageAttr.getUsername())
                    .gpu(imageAttr.getGpu())
                    .build();
            imageDetailVOS.add(imageDetailVO);
        }

        PageVO<ImageDetailVO> pageVO = PageVO.<ImageDetailVO>builder()
                .pageNum(pageInfo.getPageNum())
                .pageSize(pageInfo.getPageSize())
                .total(pageInfo.getTotal())
                .pages(pageInfo.getPages())
                .content(imageDetailVOS)
                .build();
        return Result.success(pageVO);
    }

    @ApiOperation("查询课程的镜像列表")
    @GetMapping("/course/{courseId}")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result<List<ImageDetailVO>> queryImagesByCourse(@PathVariable("courseId") Long courseId) {
        List<ImageAttr> imageAttrs = imageService.listImagesByCourseId(courseId);

        List<ImageDetailVO> imageDetailVOS = new ArrayList<>();
        for (ImageAttr imageAttr : imageAttrs) {
            ImageDetailVO imageDetailVO = ImageDetailVO.builder()
                    .imageId(imageAttr.getImageId())
                    .imageName(imageAttr.getImageName())
                    .iconUrl(LocalResourcesEnum.SYSTEM_FILE.getMappingUrl(imageAttr.getIconUrl()))
                    .description(imageAttr.getDescription())
                    .imageSource(imageAttr.getImageSource())
                    .username(imageAttr.getUsername())
                    .gpu(imageAttr.getGpu())
                    .build();
            imageDetailVOS.add(imageDetailVO);
        }

        return Result.success(imageDetailVOS);
    }

    @ApiOperation("查询镜像")
    @GetMapping("/{imageId}")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result<ImageVO> queryImage(@PathVariable("imageId") Long imageId) {
        ImageVO imageVO = imageService.getImageById(imageId, userInfoHolder.isSuperAdmin());
        if (imageVO == null) {
            throw new GlobalException("镜像不存在");
        }
        return Result.success(imageVO);
    }

    @ApiOperation("导入镜像")
    @PostMapping
    @PreAuthorize("hasRole('SUPER_ADMIN')")
    public Result importImage(@RequestBody @Valid ImageImportPO imageImportPO) {
        imageService.importImage(imageImportPO);
        return Result.success();
    }

    @ApiOperation("更新镜像")
    @PutMapping("/{imageId}")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result updateImage(@PathVariable("imageId") Long imageId,
                              @RequestBody @Valid ImageImportPO imageImportPO) {
        imageService.updateImage(imageId, imageImportPO, userInfoHolder.isSuperAdmin());
        return Result.success();
    }

    @ApiOperation("删除镜像")
    @DeleteMapping("/{imageId}")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result deleteImage(@PathVariable("imageId") Long imageId,
                              @RequestParam(defaultValue = "false") Boolean force) {
        if (!force && imageAllocationService.isImageAllocated(imageId)) {
            return Result.error(ResultEnum.IMAGE_IS_ALLOCATED);
        }
        imageService.deleteImage(imageId);
        return Result.success();
    }

    @ApiOperation("批量删除镜像")
    @PostMapping("/delete")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result<List<Long>> deleteImage(@RequestBody List<Long> imageIds,
                                          @RequestParam(defaultValue = "false") Boolean force) {
        if (!force) {
            List<Long> allocatedImageIds = imageIds.stream()
                    .filter(imageId -> imageAllocationService.isImageAllocated(imageId))
                    .collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(allocatedImageIds)) {
                List<Image> images = imageService.listImages(imageIds);
                if (CollectionUtils.isNotEmpty(images)) {
                    return new Result<>(ResultEnum.IMAGE_IS_ALLOCATED, imageIds);
                }
            }
        }
        imageService.deleteImages(imageIds);
        return Result.success();
    }

    @ApiOperation("查询教师每门课程允许的镜像最大创建数量")
    @GetMapping("/quota")
    @PreAuthorize("@permissionValidator.isAdminOrTeacher()")
    public Result<Integer> queryImageQuota() {
        Integer imageQuota = configService.getImageQuota();
        return Result.success(imageQuota);
    }

    @ApiOperation("更新教师每门课程允许的镜像最大创建数量")
    @PutMapping("/quota")
    @PreAuthorize("@permissionValidator.isAdmin()")
    public Result updateImageQuota(@RequestBody @Valid ImageQuotaUpdatePO imageQuotaUpdatePO) {
        configService.updateImageQuota(imageQuotaUpdatePO.getImageQuota());
        return Result.success();
    }

    @ApiOperation("检查镜像是否存在")
    @GetMapping("/check")
    @PreAuthorize("@permissionValidator.isAdmin()")
    public Result check() {
        imageService.check();
        return Result.success();
    }
}
